package com.windmt.filter;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.windmt.util.JsoupUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.DefaultServerRequest;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;

import java.net.URI;
import java.sql.ClientInfoStatus;
import java.util.*;

/**
 * @author Jean
 * @date
 * @des Xss 攻击过滤
 */
@Slf4j
@Component
public class XssGatewayFilterFactory extends AbstractGatewayFilterFactory implements Ordered {

    /**
     * 设置不过滤列表
     */
    private List<String> ignoreUrls = new ArrayList<>();

    @Override
    public GatewayFilter apply(Object config) {

        return (exchange, chain) -> {

            //不过滤列表，直接放行
            ServerHttpRequest request = exchange.getRequest();

            String path = request.getURI().getPath().toString();
            if (ignoreUrls.contains(path)) {
                chain.filter(exchange);
            }

            // Xss 攻击过滤
            URI uri = request.getURI();
            String queryParam = uri.getRawQuery();

            if (StringUtils.isNotBlank(queryParam)) {
                HashMap<String, String> paramMap = HttpUtil.decodeParamMap(queryParam, CharsetUtil.UTF_8);
                paramMap.forEach((key, value) -> {
                    String clean = JsoupUtil.clean(value);
                    paramMap.put(key, clean);
                });

                uri = UriComponentsBuilder.fromUri(uri)
                        .replaceQuery(HttpUtil.toParams(paramMap))
                        .build(true)
                        .toUri();
            }

            //Body过滤 排除流文件类型
            if (Method.POST.name().equalsIgnoreCase(request.getMethodValue()) && !request.getHeaders().getContentType().equals(MediaType.MULTIPART_FORM_DATA_VALUE)) {
                //Flux<DataBuffer> body = request.getBody();
                Object body = exchange.getAttribute("cachedRequestBodyObject");

            }

            log.info("执行xss过滤");
            ServerHttpRequest newRequest = request.mutate().uri(uri)
                    .headers(httpHeaders -> httpHeaders.forEach((key, value) -> {
                        value.forEach(data -> {
                            String clean = JsoupUtil.clean(data);
                            value.set(value.indexOf(data), clean);
                        });
                    })).build();

            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
        };
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
